package com.proxy.server.handler;


import com.proxy.common.entity.ClientNode;
import com.proxy.common.entity.ProxyRealServer;
import com.proxy.common.protobuf.ProxyMessageProtos;
import com.proxy.common.protocol.CommonConstant;
import com.proxy.common.util.ProxyMessageUtil;
import com.proxy.server.service.ServerBeanManager;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * 心跳处理 handler
 * @author ztgreat
 */
public class HeartBeatRespHandler extends ChannelInboundHandlerAdapter{

    private static Logger logger = LoggerFactory.getLogger(HeartBeatRespHandler.class);

    private int heartbeatCount = 0;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        if (msg instanceof  ProxyMessageProtos.ProxyMessage){

            ProxyMessageProtos.ProxyMessage message = (ProxyMessageProtos.ProxyMessage) msg;
            byte type = message.getType().toByteArray()[0];
            //如果是心跳请求消息
            if (type == CommonConstant.HearBeat.TYPE_HEARTBEAT_REQ) {
                logger.info("收到客户端心跳消息");
                //构造心态响应消息
                ProxyMessageProtos.ProxyMessage heartBeat = ProxyMessageUtil.buildHeartBeatResp();
                ctx.writeAndFlush(heartBeat);
            } else
                ctx.fireChannelRead(msg);
        }else {
            //向后转发消息
            ctx.fireChannelRead(msg);
        }

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        disConnectHandle(ctx.channel());

    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {

        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;

            switch (e.state()) {
                case READER_IDLE:
                    handleReaderIdle(ctx);
                    break;
                case WRITER_IDLE:
                    handleWriterIdle(ctx);
                    break;
                case ALL_IDLE:
                    handleAllIdle(ctx);
                    break;
                default:
                    break;
            }
        }else {
            super.userEventTriggered(ctx, evt);
        }

    }

    protected void handleReaderIdle(ChannelHandlerContext ctx) {
        timeOutHandle(ctx.channel());
        logger.debug("READER_IDLE 读超时");
    }

    protected void handleWriterIdle(ChannelHandlerContext ctx) {
        timeOutHandle(ctx.channel());
        logger.debug("WRITER_IDLE 写超时");
    }

    protected void handleAllIdle(ChannelHandlerContext ctx) {
        timeOutHandle(ctx.channel());
        logger.debug("ALL_IDLE 写超时");
    }

    /**
     * 和客户端通信超时处理(这里超时:n倍心跳时间)
     * @param channel
     */
    public  void timeOutHandle(Channel channel){
        String key= ServerBeanManager.getProxyService().getClientKey(channel);
        ClientNode node = ServerBeanManager.getProxyService().get(key);

        if(node!=null){
            //更新节点 状态(离线)
            ServerBeanManager.getProxyService().setNodeStatus(key, CommonConstant.ClientStatus.OFFLINE);

            //移除客户端 channel
            ServerBeanManager.getProxyService().setNodeChannle(key,null);

            //取消代理通道

            Map<Integer, ProxyRealServer> port2RealServers = node.getServerPort2RealServer();

            for(Map.Entry<Integer,ProxyRealServer>entry:port2RealServers.entrySet()){

                //释放绑定的代理服务器 服务端口
                ServerBeanManager.getLocalPortBindService().unBind(entry.getKey());
                ServerBeanManager.getLocalPortBindService().get(entry.getKey()).setStatus(CommonConstant.ProxyStatus.OFFLINE);
                logger.info("解绑本地服务端口({})成功 客户端({})--{}",entry.getKey(),entry.getValue().getClientKey(),entry.getValue().getDescription());
            }

            //移除客户端
            //ServerBeanManager.getProxyService().delete(key);

            //关闭连接
            channel.close();

            logger.debug("超时:代理服务器与客户端({})失去连接",node.getClientKey());
        }


    }

    /**
     * 代理服务器和客户端失去连接
     * @param channel
     */
    public  void disConnectHandle(Channel channel){
        // 获取客户端key
        String key= ServerBeanManager.getProxyService().getClientKey(channel);
        if (key!=null){
            //获取客户端节点信息
            ClientNode node= ServerBeanManager.getProxyService().get(key);
            if (node!=null){
//                node.setStatus(CommonConstant.ClientStatus.OFFLINE);
                timeOutHandle(channel);
                logger.info("代理服务器与客户端({})失去连接",node.getClientKey());
            }
        }
    }

}
